package servlets;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import javax.ejb.EJB;
import javax.persistence.criteria.CriteriaBuilder.In;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import util.MonTimerTask;
import util.TimerAttenteJoueur;
import util.TourPartie;
import be.ipl.finito.domaine.Case;
import be.ipl.finito.domaine.Grille;
import be.ipl.finito.domaine.Jeton;
import be.ipl.finito.domaine.Joueur;
import be.ipl.finito.domaine.Partie.Etat;
import be.ipl.finito.usecases.GestionJeton;
import be.ipl.finito.usecases.GestionJoueur;
import be.ipl.finito.usecases.GestionPartie;

@SuppressWarnings("serial")
@WebServlet(name = "servlet_partie.html")
public class Partie extends HttpServlet {
	
	@EJB GestionPartie gestionPartie;
	@EJB GestionJoueur gestionJoueur;
	@EJB GestionJeton gestionJeton;
	// Retient le tour courant pour les parties en cours
	private Map<Integer, TourPartie> tourParties = new HashMap<Integer, TourPartie>();
	private static Map<Integer, List<Jeton>> jetonsDebut = new HashMap<Integer, List<Jeton>>();
	private Map<Integer, Boolean> premierTour = new HashMap<Integer, Boolean>();
	private static Map<Integer, Map<Integer, List<Jeton>>> jetonsReserveStatic = new HashMap<Integer, Map<Integer, List<Jeton>>>();
	private static Map<Integer, TimerAttenteJoueur> timers = new HashMap<Integer, TimerAttenteJoueur>();
	
	
	protected synchronized void doGet(HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
		// Récupérer et tester les paramètres
		boolean test = false;
		
		Joueur joueur = (Joueur) request.getSession().getAttribute("joueur");
		if (joueur == null) {
			RequestDispatcher rd = getServletContext().getNamedDispatcher("index.html");
			rd.forward(request, response);
			return;
		}
		if (request.getSession().getAttribute("partie") == null) {
			RequestDispatcher rd = getServletContext().getNamedDispatcher("servlet_dashboard.html");
			rd.forward(request, response);
			return;
		}
		int idPartie = (int)request.getSession().getAttribute("partie");
		
		// Récupérer les variables depuis le modèle
		be.ipl.finito.domaine.Partie partie = gestionPartie.getPartie(idPartie);
		be.ipl.finito.domaine.Partie.Etat etatPartie = partie.getEtat();
		Grille grille = gestionPartie.getGrille(idPartie, joueur.getLogin());
		TourPartie tour = tourParties.get(idPartie);
		
		// Gérer les tours
		if (tour == null) {
			tour = new TourPartie(partie.getJoueurs(), partie.lancerDe());
			tourParties.put(idPartie, tour);
		}

		// Gérer l'action d'un joueur
		if (request.getParameter("case") != null && request.getParameter("jeton") != null) {
			test = true;
			int numCase = Integer.parseInt(request.getParameter("case"));
			int numJeton = Integer.parseInt(request.getParameter("jeton"));
			gestionPartie.placerJeton(grille.getId(), numCase, numJeton);
			tour.jouer(joueur.getId(),gestionJeton.getJeton(numJeton)); // si tous ont joué
			request.setAttribute("attente", "azerty");
		}else{
			request.setAttribute("attente", null);			
		}
		
		if(tour.tousOntJouee()){
			if(gestionPartie.getPartie(idPartie).getGrilles().get(1).getGrille().size()==12 || partie.getEtat() == Etat.FINIE){
				if(partie.getEtat() == Etat.EN_COURS)gestionPartie.finirPartie(idPartie);
				RequestDispatcher rd = getServletContext().getNamedDispatcher("servlet_partie_terminee.html");
				rd.forward(request, response);
				return;
			}else{
				for (Joueur jc : gestionPartie.getJoueursDunePartie(idPartie)) {
					jetonsReserveStatic.get(idPartie).get(jc.getId()).remove(gestionJeton.getJeton(tour.getJetonPlace(jc.getId())));
				}
			}
		}
		
		
		// Paramètres pour la page jsp
		request.setAttribute("de", tour.getDe());
		Map<Integer, Integer> jetonsPlaces = new HashMap<Integer, Integer>();
		List<Integer> jetonsReserve = new ArrayList<Integer>();
		Integer[] jetonsInactifs = new Integer[12];
		for (Case c : grille.getGrille())
			jetonsPlaces.put(c.getNumeroCase(), c.getJeton().getNumero());
		
		if(!premierTour.containsKey(idPartie)){
			premierTour.put(idPartie, true);
		}
		
		if(!jetonsDebut.containsKey(idPartie)){ // TOUTE PREMIERE FOIS QUON RENTRE DANS LA SERVLET POUR CETTE PARTIE
			List<Jeton> j = gestionPartie.getReserveJetonPremierTirage(idPartie);
			
			HashMap<Integer, List<Jeton>> temp = new HashMap<Integer, List<Jeton>>();
			for (Joueur jc : gestionPartie.getJoueursDunePartie(idPartie)) {
				temp.put(jc.getId(), new ArrayList<Jeton>(j));
			}
			jetonsReserveStatic.put(idPartie,temp);
			
			jetonsDebut.put(idPartie, j);
		}else{
			if(premierTour.get(idPartie)){ // PREMIER TOUR DE LA PARTIE
			}else{
				if(tour.getJeton() == null){ // PAS PREMIER TOUR ET TIRAGE PAS ENCORE FAIT
					if(!gestionPartie.indiceCourantMax(idPartie)){
						Jeton jeton = gestionPartie.tirageJeton(idPartie);
						
						for (Joueur jc : gestionPartie.getJoueursDunePartie(idPartie)) {
							jetonsReserveStatic.get(idPartie).get(jc.getId()).add(jeton);
						}
						List<Jeton> liste = jetonsDebut.get(idPartie);
						liste.add(jeton);
						jetonsDebut.put(idPartie, liste);
						tour.setJeton(jeton);
						Grille g = gestionPartie.getGrille(idPartie, joueur.getLogin());
					}
				}else{
					Grille g = gestionPartie.getGrille(idPartie, joueur.getLogin());
					for (Case casee : g.getGrille()) {
					}
				}
			}
		}

		jetonsReserve = new ArrayList<Integer>();
		for(Jeton jeto : jetonsReserveStatic.get(idPartie).get(joueur.getId())){
			jetonsReserve.add(jeto.getNumero());
		}
		
		for (int i=1; i<13; i++)
			if (!jetonsPlaces.containsValue(i) && !jetonsReserve.contains(i))
				jetonsInactifs[i - 1] = i;
		
		if(request.getParameter("jeton") != null){
			int j = Integer.parseInt(request.getParameter("jeton"));
			for (int i = 0; i < jetonsInactifs.length; i++) {
				if(jetonsInactifs[i] == j){
					jetonsInactifs[i] = -1;
				}
			}

		}
		if(tour.tousOntJouee())
			jetonsInactifs[tour.getJeton().getNumero() - 1] = -1;
		
		request.setAttribute("jetonsPlaces", jetonsPlaces);
		request.setAttribute("jetonsReserve", jetonsReserve);
		request.setAttribute("jetonsInactifs", jetonsInactifs);
		request.setAttribute("placesDeplacables", (jetonsReserve.size()==0?true:false));
		request.setAttribute("tour", tour);
		request.getSession().setAttribute("mapping", Case.MAPPING_NUMCASE_VALEUR);
		
		if(tourParties.get(idPartie).tousOntJouee()){
			premierTour.put(idPartie, false);
			tourParties.remove(idPartie);
			response.setStatus(290);			
			tourParties.put(idPartie, new TourPartie(partie.getJoueurs(), partie.lancerDe()));
		}
		
		
		
//		TimerAttenteJoueur timer = null;
//		
//		if(!timers.containsKey(tour.getId())){
//			timer = new TimerAttenteJoueur(idPartie, tour.getId());
//			MonTimerTask timerTask = new MonTimerTask(idPartie, joueur.getLogin(), tour) {
//				@Override
//				public void run() {
//					if(!this.getTour().tousOntJouee()){
////						gestionPartie.abandonnerPartie(this.getIdPartie(), this.getLogin());
//						System.out.println("MOda Foka Biatch");
////						response.setStatus(291);
//					}
//					timers.remove(this.getIdPartie()); 
//					// /!\ GET ID PARTIE RENVOI L ID DU TOUR ET NON PAS CELUI DE LA PARTie
//				}
//			};
//			timer.schedule(timerTask, TourPartie.TEMPS_MAX_TOUR);
//			timers.put(tour.getId(), timer);
//		}else{
//			timer = timers.get(tour.getId());
//		}
//		
//		request.setAttribute("timer", timer);
		
		// Etablir la liste des cases sur lesquelles on peut placer un jeton
		List<Integer> droppable = new LinkedList<Integer>();
		int numMinCaseDroppable = -1;
		int numMaxCaseDroppable = -1;
		for (int i = 1; i <= 36; i++) {
			if (Case.MAPPING_NUMCASE_VALEUR.get(i) == tour.getDe()) {
				if (numMinCaseDroppable == -1) numMinCaseDroppable = i;
				if (numMinCaseDroppable != -1 && numMaxCaseDroppable == -1) numMaxCaseDroppable = i;
				droppable.add(i);
			}
		}
		droppable.removeAll(jetonsPlaces.keySet());
		if (droppable.isEmpty()) {
			while (numMinCaseDroppable > 0 && jetonsPlaces.containsKey(numMinCaseDroppable))
				numMinCaseDroppable--;
			if (numMinCaseDroppable != 0) droppable.add(numMinCaseDroppable);
			while (numMaxCaseDroppable <= 36 && jetonsPlaces.containsKey(numMaxCaseDroppable))
				numMaxCaseDroppable++;
			if (numMinCaseDroppable != 37) droppable.add(numMaxCaseDroppable);
		}
		request.setAttribute("droppable", droppable);
		
		// Partie terminée ou annulée
		if (etatPartie == be.ipl.finito.domaine.Partie.Etat.EN_ATTENTE) {
			request.setAttribute("mikeMessage", "<script>mikeMessenger(\"Partie annul&eacute;e, vous allez &ecirc;tre exp&eacute;di&eacute; d'o&ugrave; vous &ecirc;tes venu.\", 5);window.setTimeout(function() {window.location.href = \"servlet_dashboard.html\";}, 5000);</script");
			tourParties.remove(idPartie);
			RequestDispatcher rd = getServletContext().getNamedDispatcher("partie.html");
			rd.forward(request, response);
			return;
		}
		if (gestionPartie.isPartieFini(idPartie)) {
			request.setAttribute("mikeMessage", "<script>mikeMessenger(\"Partie termin&eacute;e, vous allez bient&ocirc;t voir les r&eacute;sultats.\", 5);window.setTimeout(function() {window.location.href = \"servlet_dashboard.html\";}, 5000);</script");
			tourParties.remove(idPartie);
			RequestDispatcher rd = getServletContext().getNamedDispatcher("partie_terminee.html");
			rd.forward(request, response);
			return;
		}
		
		// Rediriger
		RequestDispatcher rd = getServletContext().getNamedDispatcher("partie.html");
		rd.forward(request, response);
		return;
	}

	protected synchronized void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}
